﻿using Digitalmes.Core.Common.Interfaces;
using Digitalmes.Core.Domain.Eitites;
using Digitalmes.Core.Messages;
using Digitalmes.Core.Services;
using ThingsEdge.Contracts;
using ThingsEdge.Router.Forwarders;

namespace Digitalmes.Infrastructure.Scada.Forwarders;

/// <summary>
/// 通知消息处理。
/// </summary>
internal sealed class NativeNoticeForwarder(IServiceScopeFactory serviceScopeFactory, 
    IMessageQueue<TurntableArchiveMessage> archiveMQ, 
    ILogger<NativeNoticeForwarder> logger) : INotificationForwarder
{
    public async Task PublishAsync(RequestMessage message, PayloadData? lastMasterPayloadData, CancellationToken cancellationToken = default)
    {
        logger.LogInformation("通知消息处理，数据：{@Value}", message.Values.Select(s => new { s.Address, s.Value }));

        var speed = message.GetData(TagDefinition.PLC_Archive_Speed)?.GetReal() ?? 0;
        var position = message.GetData(TagDefinition.PLC_Archive_Position)?.GetDInt() ?? 0;
        var forwardRotationTime = message.GetData(TagDefinition.PLC_Archive_ForwardRotationTime)?.GetDInt() ?? 0;
        var reverseRotationTime = message.GetData(TagDefinition.PLC_Archive_ReverseRotationTime)?.GetDInt() ?? 0;
        var distanceSensor = message.GetData(TagDefinition.PLC_Archive_DistanceSensor)?.GetReal() ?? 0;

        using var scope = serviceScopeFactory.CreateScope();
        var service = scope.ServiceProvider.GetRequiredService<ITurntableArchiveService>();

        TurntableArchiveRecord model = new()
        {
            ArchiveTime = DateTime.Now,
            Speed = Format(speed, 3),
            Position = position,
            ForwardRotationTime = forwardRotationTime * 0.1, // 实际值需*0.1
            ReverseRotationTime = reverseRotationTime * 0.1, // 实际值需*0.1
            DistanceSensor = Format(distanceSensor * 0.1, 3), // 实际值需*0.1
        };
        await service.ArchiveAsync(model);
        await archiveMQ.EnqueueAsync(new TurntableArchiveMessage(
            model.Speed,
            model.Position,
            model.ForwardRotationTime,
            model.ReverseRotationTime,
            model.DistanceSensor), cancellationToken).ConfigureAwait(false);
    }

    private static double Format(double value, int digits)
    {
        return Math.Round(value, digits);
    }
}
